using System;
using System.Threading;
using UnityEngine;

[Serializable]
public class JPGEncoder_class
{
	private int[] ZigZag;

	private int[] YTable;

	private int[] UVTable;

	private float[] fdtbl_Y;

	private float[] fdtbl_UV;

	private BitString[] YDC_HT;

	private BitString[] UVDC_HT;

	private BitString[] YAC_HT;

	private BitString[] UVAC_HT;

	private int[] std_dc_luminance_nrcodes;

	private int[] std_dc_luminance_values;

	private int[] std_ac_luminance_nrcodes;

	private int[] std_ac_luminance_values;

	private int[] std_dc_chrominance_nrcodes;

	private int[] std_dc_chrominance_values;

	private int[] std_ac_chrominance_nrcodes;

	private int[] std_ac_chrominance_values;

	private BitString[] bitcode;

	private int[] category;

	private int bytenew;

	private int bytepos;

	private ByteArray byteout;

	private int[] DU;

	private float[] YDU;

	private float[] UDU;

	private float[] VDU;

	public bool isDone;

	private BitmapData image;

	private int sf;

	public JPGEncoder_class(Texture2D texture, float quality)
	{
		ZigZag = new int[64]
		{
			0,
			1,
			5,
			6,
			14,
			15,
			27,
			28,
			2,
			4,
			7,
			13,
			16,
			26,
			29,
			42,
			3,
			8,
			12,
			17,
			25,
			30,
			41,
			43,
			9,
			11,
			18,
			24,
			31,
			40,
			44,
			53,
			10,
			19,
			23,
			32,
			39,
			45,
			52,
			54,
			20,
			22,
			33,
			38,
			46,
			51,
			55,
			60,
			21,
			34,
			37,
			47,
			50,
			56,
			59,
			61,
			35,
			36,
			48,
			49,
			57,
			58,
			62,
			63
		};
		YTable = new int[64];
		UVTable = new int[64];
		fdtbl_Y = new float[64];
		fdtbl_UV = new float[64];
		std_dc_luminance_nrcodes = new int[17]
		{
			0,
			0,
			1,
			5,
			1,
			1,
			1,
			1,
			1,
			1,
			0,
			0,
			0,
			0,
			0,
			0,
			0
		};
		std_dc_luminance_values = new int[12]
		{
			0,
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11
		};
		std_ac_luminance_nrcodes = new int[17]
		{
			0,
			0,
			2,
			1,
			3,
			3,
			2,
			4,
			3,
			5,
			5,
			4,
			4,
			0,
			0,
			1,
			125
		};
		std_ac_luminance_values = new int[162]
		{
			1,
			2,
			3,
			0,
			4,
			17,
			5,
			18,
			33,
			49,
			65,
			6,
			19,
			81,
			97,
			7,
			34,
			113,
			20,
			50,
			129,
			145,
			161,
			8,
			35,
			66,
			177,
			193,
			21,
			82,
			209,
			240,
			36,
			51,
			98,
			114,
			130,
			9,
			10,
			22,
			23,
			24,
			25,
			26,
			37,
			38,
			39,
			40,
			41,
			42,
			52,
			53,
			54,
			55,
			56,
			57,
			58,
			67,
			68,
			69,
			70,
			71,
			72,
			73,
			74,
			83,
			84,
			85,
			86,
			87,
			88,
			89,
			90,
			99,
			100,
			101,
			102,
			103,
			104,
			105,
			106,
			115,
			116,
			117,
			118,
			119,
			120,
			121,
			122,
			131,
			132,
			133,
			134,
			135,
			136,
			137,
			138,
			146,
			147,
			148,
			149,
			150,
			151,
			152,
			153,
			154,
			162,
			163,
			164,
			165,
			166,
			167,
			168,
			169,
			170,
			178,
			179,
			180,
			181,
			182,
			183,
			184,
			185,
			186,
			194,
			195,
			196,
			197,
			198,
			199,
			200,
			201,
			202,
			210,
			211,
			212,
			213,
			214,
			215,
			216,
			217,
			218,
			225,
			226,
			227,
			228,
			229,
			230,
			231,
			232,
			233,
			234,
			241,
			242,
			243,
			244,
			245,
			246,
			247,
			248,
			249,
			250
		};
		std_dc_chrominance_nrcodes = new int[17]
		{
			0,
			0,
			3,
			1,
			1,
			1,
			1,
			1,
			1,
			1,
			1,
			1,
			0,
			0,
			0,
			0,
			0
		};
		std_dc_chrominance_values = new int[12]
		{
			0,
			1,
			2,
			3,
			4,
			5,
			6,
			7,
			8,
			9,
			10,
			11
		};
		std_ac_chrominance_nrcodes = new int[17]
		{
			0,
			0,
			2,
			1,
			2,
			4,
			4,
			3,
			4,
			7,
			5,
			4,
			4,
			0,
			1,
			2,
			119
		};
		std_ac_chrominance_values = new int[162]
		{
			0,
			1,
			2,
			3,
			17,
			4,
			5,
			33,
			49,
			6,
			18,
			65,
			81,
			7,
			97,
			113,
			19,
			34,
			50,
			129,
			8,
			20,
			66,
			145,
			161,
			177,
			193,
			9,
			35,
			51,
			82,
			240,
			21,
			98,
			114,
			209,
			10,
			22,
			36,
			52,
			225,
			37,
			241,
			23,
			24,
			25,
			26,
			38,
			39,
			40,
			41,
			42,
			53,
			54,
			55,
			56,
			57,
			58,
			67,
			68,
			69,
			70,
			71,
			72,
			73,
			74,
			83,
			84,
			85,
			86,
			87,
			88,
			89,
			90,
			99,
			100,
			101,
			102,
			103,
			104,
			105,
			106,
			115,
			116,
			117,
			118,
			119,
			120,
			121,
			122,
			130,
			131,
			132,
			133,
			134,
			135,
			136,
			137,
			138,
			146,
			147,
			148,
			149,
			150,
			151,
			152,
			153,
			154,
			162,
			163,
			164,
			165,
			166,
			167,
			168,
			169,
			170,
			178,
			179,
			180,
			181,
			182,
			183,
			184,
			185,
			186,
			194,
			195,
			196,
			197,
			198,
			199,
			200,
			201,
			202,
			210,
			211,
			212,
			213,
			214,
			215,
			216,
			217,
			218,
			226,
			227,
			228,
			229,
			230,
			231,
			232,
			233,
			234,
			242,
			243,
			244,
			245,
			246,
			247,
			248,
			249,
			250
		};
		bitcode = new BitString[65535];
		category = new int[65535];
		bytepos = 7;
		byteout = new ByteArray();
		DU = new int[64];
		YDU = new float[64];
		UDU = new float[64];
		VDU = new float[64];
		image = new BitmapData(texture);
		if (!(quality > 0f))
		{
			quality = 1f;
		}
		if (!(quality <= 100f))
		{
			quality = 100f;
		}
		if (!(quality >= 50f))
		{
			sf = (int)(5000f / quality);
		}
		else
		{
			sf = (int)(200f - quality * 2f);
		}
		Thread thread = new Thread(doEncoding);
		thread.Start();
	}

	private void initQuantTables(int sf)
	{
		int num = default(int);
		float num2 = default(float);
		int[] array = new int[64]
		{
			16,
			11,
			10,
			16,
			24,
			40,
			51,
			61,
			12,
			12,
			14,
			19,
			26,
			58,
			60,
			55,
			14,
			13,
			16,
			24,
			40,
			57,
			69,
			56,
			14,
			17,
			22,
			29,
			51,
			87,
			80,
			62,
			18,
			22,
			37,
			56,
			68,
			109,
			103,
			77,
			24,
			35,
			55,
			64,
			81,
			104,
			113,
			92,
			49,
			64,
			78,
			87,
			103,
			121,
			120,
			101,
			72,
			92,
			95,
			98,
			112,
			100,
			103,
			99
		};
		for (num = 0; num < 64; num++)
		{
			num2 = Mathf.Floor((array[num] * sf + 50) / 100);
			if (!(num2 >= 1f))
			{
				num2 = 1f;
			}
			else if (!(num2 <= 255f))
			{
				num2 = 255f;
			}
			YTable[ZigZag[num]] = (int)num2;
		}
		int[] array2 = new int[64]
		{
			17,
			18,
			24,
			47,
			99,
			99,
			99,
			99,
			18,
			21,
			26,
			66,
			99,
			99,
			99,
			99,
			24,
			26,
			56,
			99,
			99,
			99,
			99,
			99,
			47,
			66,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99,
			99
		};
		for (num = 0; num < 64; num++)
		{
			num2 = Mathf.Floor((array2[num] * sf + 50) / 100);
			if (!(num2 >= 1f))
			{
				num2 = 1f;
			}
			else if (!(num2 <= 255f))
			{
				num2 = 255f;
			}
			UVTable[ZigZag[num]] = (int)num2;
		}
		float[] array3 = new float[8]
		{
			1f,
			1.3870399f,
			1.306563f,
			1.17587554f,
			1f,
			0.785694957f,
			0.5411961f,
			0.27589938f
		};
		num = 0;
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				fdtbl_Y[num] = 1f / ((float)YTable[ZigZag[num]] * array3[i] * array3[j] * 8f);
				fdtbl_UV[num] = 1f / ((float)UVTable[ZigZag[num]] * array3[i] * array3[j] * 8f);
				num++;
			}
		}
	}

	private BitString[] computeHuffmanTbl(int[] nrcodes, int[] std_table)
	{
		int num = 0;
		int num2 = 0;
		BitString[] array = new BitString[256];
		for (int i = 1; i <= 16; i++)
		{
			for (int j = 1; j <= nrcodes[i]; j++)
			{
				array[std_table[num2]] = new BitString();
				array[std_table[num2]].val = num;
				array[std_table[num2]].len = i;
				num2++;
				num++;
			}
			num *= 2;
		}
		return array;
	}

	private void initHuffmanTbl()
	{
		YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
		UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
		YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
		UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
	}

	private void initCategoryfloat()
	{
		int num = 1;
		int num2 = 2;
		int num3 = default(int);
		BitString bitString = null;
		for (int i = 1; i <= 15; i++)
		{
			for (num3 = num; num3 < num2; num3++)
			{
				category[32767 + num3] = i;
				bitString = new BitString();
				bitString.len = i;
				bitString.val = num3;
				bitcode[32767 + num3] = bitString;
			}
			for (num3 = -(num2 - 1); num3 <= -num; num3++)
			{
				category[32767 + num3] = i;
				bitString = new BitString();
				bitString.len = i;
				bitString.val = num2 - 1 + num3;
				bitcode[32767 + num3] = bitString;
			}
			num <<= 1;
			num2 <<= 1;
		}
	}

	public byte[] GetBytes()
	{
		object result;
		if (!isDone)
		{
			UnityEngine.Debug.LogError("JPEGEncoder not complete, cannot get bytes!");
			result = null;
		}
		else
		{
			result = byteout.GetAllBytes();
		}
		return (byte[])result;
	}

	private void writeBits(BitString bs)
	{
		int val = bs.val;
		int num = bs.len - 1;
		while (num >= 0)
		{
			if (((long)val & (long)(int)Convert.ToUInt32(1 << num)) != 0)
			{
				bytenew = (int)((long)bytenew | (long)(int)Convert.ToUInt32(1 << bytepos));
			}
			num--;
			bytepos--;
			if (bytepos < 0)
			{
				if (bytenew == 255)
				{
					writeByte(byte.MaxValue);
					writeByte(0);
				}
				else
				{
					writeByte((byte)bytenew);
				}
				bytepos = 7;
				bytenew = 0;
			}
		}
	}

	private void writeByte(byte value)
	{
		byteout.writeByte(value);
	}

	private void writeWord(int value)
	{
		writeByte((byte)((value >> 8) & 0xFF));
		writeByte((byte)(value & 0xFF));
	}

	private float[] fDCTQuant(float[] data, float[] fdtbl)
	{
		float num = default(float);
		float num2 = default(float);
		float num3 = default(float);
		float num4 = default(float);
		float num5 = default(float);
		float num6 = default(float);
		float num7 = default(float);
		float num8 = default(float);
		float num9 = default(float);
		float num10 = default(float);
		float num11 = default(float);
		float num12 = default(float);
		float num13 = default(float);
		float num14 = default(float);
		float num15 = default(float);
		float num16 = default(float);
		float num17 = default(float);
		float num18 = default(float);
		float num19 = default(float);
		int num20 = default(int);
		int num21 = 0;
		for (num20 = 0; num20 < 8; num20++)
		{
			num = data[num21 + 0] + data[num21 + 7];
			num8 = data[num21 + 0] - data[num21 + 7];
			num2 = data[num21 + 1] + data[num21 + 6];
			num7 = data[num21 + 1] - data[num21 + 6];
			num3 = data[num21 + 2] + data[num21 + 5];
			num6 = data[num21 + 2] - data[num21 + 5];
			num4 = data[num21 + 3] + data[num21 + 4];
			num5 = data[num21 + 3] - data[num21 + 4];
			num9 = num + num4;
			num12 = num - num4;
			num10 = num2 + num3;
			num11 = num2 - num3;
			data[num21 + 0] = num9 + num10;
			data[num21 + 4] = num9 - num10;
			num13 = (num11 + num12) * 0.707106769f;
			data[num21 + 2] = num12 + num13;
			data[num21 + 6] = num12 - num13;
			num9 = num5 + num6;
			num10 = num6 + num7;
			num11 = num7 + num8;
			num17 = (num9 - num11) * 0.382683426f;
			num14 = 0.5411961f * num9 + num17;
			num16 = 1.306563f * num11 + num17;
			num15 = num10 * 0.707106769f;
			num18 = num8 + num15;
			num19 = num8 - num15;
			data[num21 + 5] = num19 + num14;
			data[num21 + 3] = num19 - num14;
			data[num21 + 1] = num18 + num16;
			data[num21 + 7] = num18 - num16;
			num21 += 8;
		}
		num21 = 0;
		for (num20 = 0; num20 < 8; num20++)
		{
			num = data[num21 + 0] + data[num21 + 56];
			num8 = data[num21 + 0] - data[num21 + 56];
			num2 = data[num21 + 8] + data[num21 + 48];
			num7 = data[num21 + 8] - data[num21 + 48];
			num3 = data[num21 + 16] + data[num21 + 40];
			num6 = data[num21 + 16] - data[num21 + 40];
			num4 = data[num21 + 24] + data[num21 + 32];
			num5 = data[num21 + 24] - data[num21 + 32];
			num9 = num + num4;
			num12 = num - num4;
			num10 = num2 + num3;
			num11 = num2 - num3;
			data[num21 + 0] = num9 + num10;
			data[num21 + 32] = num9 - num10;
			num13 = (num11 + num12) * 0.707106769f;
			data[num21 + 16] = num12 + num13;
			data[num21 + 48] = num12 - num13;
			num9 = num5 + num6;
			num10 = num6 + num7;
			num11 = num7 + num8;
			num17 = (num9 - num11) * 0.382683426f;
			num14 = 0.5411961f * num9 + num17;
			num16 = 1.306563f * num11 + num17;
			num15 = num10 * 0.707106769f;
			num18 = num8 + num15;
			num19 = num8 - num15;
			data[num21 + 40] = num19 + num14;
			data[num21 + 24] = num19 - num14;
			data[num21 + 8] = num18 + num16;
			data[num21 + 56] = num18 - num16;
			num21++;
		}
		for (num20 = 0; num20 < 64; num20++)
		{
			data[num20] = Mathf.Round(data[num20] * fdtbl[num20]);
		}
		return data;
	}

	private void writeAPP0()
	{
		writeWord(65504);
		writeWord(16);
		writeByte(74);
		writeByte(70);
		writeByte(73);
		writeByte(70);
		writeByte(0);
		writeByte(1);
		writeByte(1);
		writeByte(0);
		writeWord(1);
		writeWord(1);
		writeByte(0);
		writeByte(0);
	}

	private void writeSOF0(int width, int height)
	{
		writeWord(65472);
		writeWord(17);
		writeByte(8);
		writeWord(height);
		writeWord(width);
		writeByte(3);
		writeByte(1);
		writeByte(17);
		writeByte(0);
		writeByte(2);
		writeByte(17);
		writeByte(1);
		writeByte(3);
		writeByte(17);
		writeByte(1);
	}

	private void writeDQT()
	{
		writeWord(65499);
		writeWord(132);
		writeByte(0);
		int num = default(int);
		for (num = 0; num < 64; num++)
		{
			writeByte((byte)YTable[num]);
		}
		writeByte(1);
		for (num = 0; num < 64; num++)
		{
			writeByte((byte)UVTable[num]);
		}
	}

	private void writeDHT()
	{
		writeWord(65476);
		writeWord(418);
		int num = default(int);
		writeByte(0);
		for (num = 0; num < 16; num++)
		{
			writeByte((byte)std_dc_luminance_nrcodes[num + 1]);
		}
		for (num = 0; num <= 11; num++)
		{
			writeByte((byte)std_dc_luminance_values[num]);
		}
		writeByte(16);
		for (num = 0; num < 16; num++)
		{
			writeByte((byte)std_ac_luminance_nrcodes[num + 1]);
		}
		for (num = 0; num <= 161; num++)
		{
			writeByte((byte)std_ac_luminance_values[num]);
		}
		writeByte(1);
		for (num = 0; num < 16; num++)
		{
			writeByte((byte)std_dc_chrominance_nrcodes[num + 1]);
		}
		for (num = 0; num <= 11; num++)
		{
			writeByte((byte)std_dc_chrominance_values[num]);
		}
		writeByte(17);
		for (num = 0; num < 16; num++)
		{
			writeByte((byte)std_ac_chrominance_nrcodes[num + 1]);
		}
		for (num = 0; num <= 161; num++)
		{
			writeByte((byte)std_ac_chrominance_values[num]);
		}
	}

	private void writeSOS()
	{
		writeWord(65498);
		writeWord(12);
		writeByte(3);
		writeByte(1);
		writeByte(0);
		writeByte(2);
		writeByte(17);
		writeByte(3);
		writeByte(17);
		writeByte(0);
		writeByte(63);
		writeByte(0);
	}

	private float processDU(float[] CDU, float[] fdtbl, float DC, BitString[] HTDC, BitString[] HTAC)
	{
		BitString bs = HTAC[0];
		BitString bs2 = HTAC[240];
		int num = default(int);
		float[] array = fDCTQuant(CDU, fdtbl);
		for (num = 0; num < 64; num++)
		{
			DU[ZigZag[num]] = (int)array[num];
		}
		int num2 = (int)((float)DU[0] - DC);
		DC = DU[0];
		if (num2 == 0)
		{
			writeBits(HTDC[0]);
		}
		else
		{
			writeBits(HTDC[category[32767 + num2]]);
			writeBits(bitcode[32767 + num2]);
		}
		int num3 = 63;
		while (num3 > 0 && DU[num3] == 0)
		{
			num3--;
		}
		float result;
		if (num3 == 0)
		{
			writeBits(bs);
			result = DC;
		}
		else
		{
			for (num = 1; num <= num3; num++)
			{
				int num4 = num;
				for (; DU[num] == 0 && num <= num3; num++)
				{
				}
				int num5 = num - num4;
				if (num5 >= 16)
				{
					for (int i = 1; i <= num5 / 16; i++)
					{
						writeBits(bs2);
					}
					num5 &= 0xF;
				}
				writeBits(HTAC[num5 * 16 + category[32767 + DU[num]]]);
				writeBits(bitcode[32767 + DU[num]]);
			}
			if (num3 != 63)
			{
				writeBits(bs);
			}
			result = DC;
		}
		return result;
	}

	private void RGB2YUV(BitmapData img, int xpos, int ypos)
	{
		int num = 0;
		for (int i = 0; i < 8; i++)
		{
			for (int j = 0; j < 8; j++)
			{
				Color pixelColor = img.getPixelColor(xpos + j, img.height - (ypos + i));
				float num2 = pixelColor.r * 255f;
				float num3 = pixelColor.g * 255f;
				float num4 = pixelColor.b * 255f;
				YDU[num] = 0.299f * num2 + 0.587f * num3 + 0.114f * num4 - 128f;
				UDU[num] = -0.16874f * num2 + -0.33126f * num3 + 0.5f * num4;
				VDU[num] = 0.5f * num2 + -0.41869f * num3 + -0.08131f * num4;
				num++;
			}
		}
	}

	private void doEncoding()
	{
		isDone = false;
		Thread.Sleep(5);
		initHuffmanTbl();
		initCategoryfloat();
		initQuantTables(sf);
		encode();
		isDone = true;
		image = null;
		Thread.CurrentThread.Abort();
	}

	private void encode()
	{
		byteout = new ByteArray();
		bytenew = 0;
		bytepos = 7;
		writeWord(65496);
		writeAPP0();
		writeDQT();
		writeSOF0(image.width, image.height);
		writeDHT();
		writeSOS();
		float dC = 0f;
		float dC2 = 0f;
		float dC3 = 0f;
		bytenew = 0;
		bytepos = 7;
		for (int i = 0; i < image.height; i += 8)
		{
			for (int j = 0; j < image.width; j += 8)
			{
				RGB2YUV(image, j, i);
				dC = processDU(YDU, fdtbl_Y, dC, YDC_HT, YAC_HT);
				dC2 = processDU(UDU, fdtbl_UV, dC2, UVDC_HT, UVAC_HT);
				dC3 = processDU(VDU, fdtbl_UV, dC3, UVDC_HT, UVAC_HT);
				Thread.Sleep(0);
			}
		}
		if (bytepos >= 0)
		{
			BitString bitString = new BitString();
			bitString.len = bytepos + 1;
			bitString.val = (1 << bytepos + 1) - 1;
			writeBits(bitString);
		}
		writeWord(65497);
		isDone = true;
	}
}
